/**** Code for Node 3 ********/
/*********************/
/** Startup.java */
/*********************/
package atag.apps.mainApp;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import java.util.Vector;

import atag.common.*;
import atag.runtime.*;
import atag.runtime.ln.*;
import atag.runtime.ln.nodeAttributes.*;
import atag.runtime.platformDependent.*;

public class Startup extends Service{
    
    private static int nextNodeId = 0;
    
    private static final int RANDOM_SEED = 12345;
    
    public static void createNode(NodeInfo info,
            ATaGProgram atagPrg){// throws NoSuchMethodException {
        
        int id = info.getMyId();
        
        // Create entities
        
        
        /*DatagramObjectIO objectIO = new DatagramObjectIO(
                LogicalNeighborhood.PORT, LogicalNeighborhood.BUFFER_SIZE,
                LogicalNeighborhood.RECEIVE_TIMEOUT);
        objectIO.start();
        Utils.sleep(1);*/
        
        
        final LogicalNeighborhoods ln = new LogicalNeighborhoods(adapterNodeInfotoNode(info));
        
        
        AtagManager atagManager = new PreBuiltAtagManager();
        atagManager.setAtagProgram(atagPrg);
        atagManager.setNodeInfo(info);
        atagManager.setDataPool(new DataPool(ln, info, atagManager));
        atagManager.setUp();
        //start the ATaG Manager
        atagManager.start();
        
        
        
    }
    
     public static Node adapterNodeInfotoNode(NodeInfo info)
     {
         return new Node(info.getMyId(),info.getNodeAttributes(),info.getSendingCost());
     }

    
    
    
    public static ATaGProgram returnMainApplication() {
        
        ATaGTaskDeclaration newTask;
        int[] tempFiringRule;
        int[] tempTaskLocation;
        
        ATaGProgram retProgram = new ATaGProgram();
        
        // set the tasks
        Vector tList = retProgram.getTaskList();
        
        // SenseLight
        newTask = new ATaGTaskDeclaration();
        newTask.setName("SenseLight");
        
        tempFiringRule = new int[2];
        tempFiringRule[0] = ATaGTaskDeclaration.FIRING_PERIODIC;
        tempFiringRule[1] = 10;
        newTask.setFiringRule(tempFiringRule);
        newTask.setRunAtInit(true);
        
        tempTaskLocation = new int[2];
        tempTaskLocation[0] = ATaGTaskDeclaration.INSTANTIATION_NODES_PER_INSTANCE;
        // set number of nodes per instance as the other element
        tempTaskLocation[1] = 1;
        newTask.setLocation(tempTaskLocation);
        newTask.setAt(false);
        newTask.setSlash(false);
        newTask.setMyRegionName(new String("Room"));
        newTask.setNeededAttribute(new StringSetAttribute("attachedSensors",
                new String[] { "LightSensor" }));
        
        tList.addElement(newTask);
        
        
        // ActuateLight
        newTask = new ATaGTaskDeclaration();
        newTask.setName("ActuateLight");
        
        tempFiringRule = new int[2];
        tempFiringRule[0] = ATaGTaskDeclaration.FIRING_ANYDATA;
        tempFiringRule[1] = 0;
        newTask.setFiringRule(tempFiringRule);
        newTask.setRunAtInit(false);
        
        tempTaskLocation = new int[2];
        tempTaskLocation[0] = ATaGTaskDeclaration.INSTANTIATION_NODES_PER_INSTANCE;
        // set number of nodes per instance as the other element
        tempTaskLocation[1] = 1;
        newTask.setLocation(tempTaskLocation);
        newTask.setAt(false);
        newTask.setSlash(false);
        newTask.setMyRegionName(new String("Room"));
        newTask.setNeededAttribute(new StringSetAttribute("attachedActuators",
                new String[] { "LightActuator" }));
        
        tList.addElement(newTask);
        
        
        // SenseRFID
        newTask = new ATaGTaskDeclaration();
        newTask.setName("SenseRFID");
        
        tempFiringRule = new int[2];
        tempFiringRule[0] = ATaGTaskDeclaration.FIRING_TRIGGERED;
        tempFiringRule[1] = 0;
        newTask.setFiringRule(tempFiringRule);
        newTask.setRunAtInit(true);
        
        tempTaskLocation = new int[2];
        tempTaskLocation[0] = ATaGTaskDeclaration.INSTANTIATION_NODES_PER_INSTANCE;
        // set number of nodes per instance as the other element
        tempTaskLocation[1] = 1;
        newTask.setLocation(tempTaskLocation);
        newTask.setAt(false);
        newTask.setSlash(false);
        newTask.setMyRegionName(new String("Room"));
        newTask.setNeededAttribute(new StringSetAttribute("attachedSensors",
                new String[] { "RFIDSensor" }));
        
        tList.addElement(newTask);
        
        
        // ProcessLightInfo
        newTask = new ATaGTaskDeclaration();
        newTask.setName("ProcessLightInfo");
        
        tempFiringRule = new int[2];
        tempFiringRule[0] = ATaGTaskDeclaration.FIRING_ANYDATA;
        tempFiringRule[1] = 0;
        newTask.setFiringRule(tempFiringRule);
        newTask.setRunAtInit(false);
        
        tempTaskLocation = new int[2];
        tempTaskLocation[0] = ATaGTaskDeclaration.INSTANTIATION_PARTITION_PER_INSTANCE;
        // set number of nodes per instance as the other element
        tempTaskLocation[1] = 1;
        newTask.setLocation(tempTaskLocation);
        newTask.setAt(false);
        newTask.setSlash(false);
        newTask.setMyRegionName(new String("Room"));
        
        tList.addElement(newTask);
        
        
        // ProcessRFID
        newTask = new ATaGTaskDeclaration();
        newTask.setName("ProcessRFID");
        
        tempFiringRule = new int[2];
        tempFiringRule[0] = ATaGTaskDeclaration.FIRING_ANYDATA;
        tempFiringRule[1] = 0;
        newTask.setFiringRule(tempFiringRule);
        newTask.setRunAtInit(false);
        
        tempTaskLocation = new int[2];
        tempTaskLocation[0] = ATaGTaskDeclaration.INSTANTIATION_NODES_PER_INSTANCE;
        // set number of nodes per instance as the other element
        tempTaskLocation[1] = 1;
        newTask.setLocation(tempTaskLocation);
        newTask.setAt(false);
        newTask.setSlash(false);
        newTask.setMyRegionName(new String("Room"));
        newTask.setNeededAttribute(new StringSetAttribute("attachedSensors",
                new String[] { "RFIDSensor" }));
        
        tList.addElement(newTask);
        
        
        // ControlLightSetting
        newTask = new ATaGTaskDeclaration();
        newTask.setName("ControlLightSetting");
        
        tempFiringRule = new int[2];
        tempFiringRule[0] = ATaGTaskDeclaration.FIRING_TRIGGERED;
        tempFiringRule[1] = 0;
        newTask.setFiringRule(tempFiringRule);
        newTask.setRunAtInit(false);
        
        tempTaskLocation = new int[2];
        tempTaskLocation[0] = ATaGTaskDeclaration.INSTANTIATION_NODES_PER_INSTANCE;
        // set number of nodes per instance as the other element
        tempTaskLocation[1] = 1;
        newTask.setLocation(tempTaskLocation);
        newTask.setAt(false);
        newTask.setSlash(false);
        newTask.setMyRegionName(new String("Remote"));
        newTask.setNeededAttribute(new StringSetAttribute("attachedSensors",
                new String[] { "GUI" }));
        
        tList.addElement(newTask);
        
        
        // Authenticate
        newTask = new ATaGTaskDeclaration();
        newTask.setName("Authenticate");
        
        tempFiringRule = new int[2];
        tempFiringRule[0] = ATaGTaskDeclaration.FIRING_TRIGGERED;
        tempFiringRule[1] = 0;
        newTask.setFiringRule(tempFiringRule);
        newTask.setRunAtInit(false);
        
        tempTaskLocation = new int[2];
        tempTaskLocation[0] = ATaGTaskDeclaration.INSTANTIATION_NODES_PER_INSTANCE;
        // set number of nodes per instance as the other element
        tempTaskLocation[1] = 1;
        newTask.setLocation(tempTaskLocation);
        newTask.setAt(false);
        newTask.setSlash(false);
        newTask.setMyRegionName(new String("Remote"));
        newTask.setNeededAttribute(new StringSetAttribute("attachedSensors",
                new String[] { "GUI" }));
        
        tList.addElement(newTask);
        
        
        // now populate the data list
        Vector dList = retProgram.getDataList();
        ATaGDataItemDeclaration newDataItem;
        newDataItem = new ATaGDataItemDeclaration();
        newDataItem.setName(new String("LightReading"));
        dList.addElement(newDataItem);
        
        newDataItem = new ATaGDataItemDeclaration();
        newDataItem.setName(new String("Action"));
        dList.addElement(newDataItem);
        
        newDataItem = new ATaGDataItemDeclaration();
        newDataItem.setName(new String("RFIDLightSetting"));
        dList.addElement(newDataItem);
        
        newDataItem = new ATaGDataItemDeclaration();
        newDataItem.setName(new String("ControllerLightSetting"));
        dList.addElement(newDataItem);
        
        newDataItem = new ATaGDataItemDeclaration();
        newDataItem.setName(new String("RFID"));
        dList.addElement(newDataItem);
        
        newDataItem = new ATaGDataItemDeclaration();
        newDataItem.setName(new String("LightInfoRequest"));
        dList.addElement(newDataItem);
        
        newDataItem = new ATaGDataItemDeclaration();
        newDataItem.setName(new String("LightInfoResponse"));
        dList.addElement(newDataItem);
        
        
        // now populate the channel list
        Vector cList = retProgram.getChannelList();
        ScopedChannel newChannel;
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("LightReading"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_OUTPUT);
        newChannel.setInterest(new String("none:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("SenseLight"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("LightReading"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_INPUT);
        newChannel.setInterest(new String("domain:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("ProcessLightInfo"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("Action"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_OUTPUT);
        newChannel.setInterest(new String("domain:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("ProcessLightInfo"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("Action"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_INPUT);
        newChannel.setInterest(new String("none:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("ActuateLight"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("RFID"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_OUTPUT);
        newChannel.setInterest(new String("none:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("SenseRFID"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("RFID"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_INPUT);
        newChannel.setInterest(new String("none:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("ProcessRFID"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("RFIDLightSetting"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_OUTPUT);
        newChannel.setInterest(new String("none:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("ProcessRFID"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("RFIDLightSetting"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_INPUT);
        newChannel.setInterest(new String("domain:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("ProcessLightInfo"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("ControllerLightSetting"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_OUTPUT);
        newChannel.setInterest(new String("none:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("ControlLightSetting"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("ControllerLightSetting"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_INPUT);
        newChannel.setInterest(new String("custom:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("ProcessLightInfo"));
        cList.addElement(newChannel);
        
        newChannel = new ScopedChannel();
        newChannel.setDataName(new String("LightInfoRequest LightInfoResponse"));
        newChannel.setDirection(ScopedChannel.CHANNEL_TYPE_REQUEST_RESPONSE);
        newChannel.setInterest(new String("custom:0"));
        newChannel.setLocalFlag(true);
        newChannel.setTaskName(new String("ControlLightSetting ProcessLightInfo"));
        cList.addElement(newChannel);
        
        return retProgram;
    }
    
    /**
     * Node-per-node setup.
     */
    private static NodeInfo setUpNode() {
        NodeInfo retNode=null;
        Vector attributes, assignedTasks;
        int regionID;//My Region
        float x;//My X Coordinate
        float y;//My Y Coordinate
        int id;//My ID
        id = 3; // 
        regionID = 0;
        x = (float)400.0;
        y = (float)400.0;
        
        
        // Creating the node
        attributes = new Vector();
        attributes.addElement(new IntegerAttribute("Remote", regionID));
        String ip[]={"192.168.2.100","192.168.2.102"};
        attributes.addElement(new StringSetAttribute("ip",ip));
        assignedTasks = new Vector();
        System.out.println("Placing ControlLightSetting on node id "
                + id + " in Floor " + regionID + " at " + x + "," + y);
        assignedTasks.addElement(String.valueOf(IDConstants.T_CONTROLLIGHTSETTING));
        
        System.out.println("Placing Authenticate on node id "
                + id + " in Floor " + regionID + " at " + x + "," + y);
        assignedTasks.addElement(String.valueOf(IDConstants.T_AUTHENTICATE));
        
		// get the ability Label
		String abilityString = "attachedSensors:GUI";
		String[] abilityInfo = StringHelper.splitString(abilityString, ':');
		if (!(abilityInfo[0].equalsIgnoreCase("none"))) {
			int count = 0;
			while (count < abilityInfo.length) {
				String setName = abilityInfo[count++];
				String memberName = abilityInfo[count++];
				attributes.addElement(new StringSetAttribute(setName, 
						StringHelper.splitString(memberName, ',')));
			}
		}
        retNode =  new NodeInfo(id,
                new NodeLocation(x, y), attributes, 1, assignedTasks,
                new SunSPOTClock());
        
        retNode.setRegionLabel("Remote");
        retNode.setAbilityString("attachedSensors:GUI");
        return retNode;
        
    }
    
   @Override
   public void onCreate() { 
       super.onCreate(); 
       Log.i("Info:", "Service started"); 
       try { 

           ATaGProgram atagPrg = returnMainApplication(); 
           atagPrg.sanitize(); 

           NodeInfo n = setUpNode(); 
           createNode(n, atagPrg); 
 
           } catch (Exception e) { 
           Log.e("Exception during startup", e.getMessage(), e); 
           } 
   } 
   
   @Override 
   public IBinder onBind(Intent arg0) { 
       return null; 
   } 
}
